package com.apobates.forum.core.impl.dao;

import com.apobates.forum.core.dao.BoardTopicCategoryIndexDao;
import com.apobates.forum.core.entity.BoardTopicCategoryIndex;
import com.apobates.forum.core.entity.TopicCategory;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author xiaofanku
 * @since 20200525
 */
@Repository
public class BoardTopicCategoryIndexDaoImpl implements BoardTopicCategoryIndexDao{
    @PersistenceContext
    private EntityManager entityManager;
    @Value("${jpa.batch.size}")
    private int batchSize;
    
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public int batchSave(List<BoardTopicCategoryIndex> entities) {
        int i = 0;
        for (BoardTopicCategoryIndex btc : entities) {
            entityManager.persist(btc);
            i++;
            if (i % batchSize == 0) {
                // Flush a batch of inserts and release memory.
                entityManager.flush();
                entityManager.clear();
            }
        }
        return i;
    }
    
    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public int delete(long boardId, Collection<Integer> categoryIdSet) {
        if (categoryIdSet == null || categoryIdSet.isEmpty()) {
            return -1;
        }
        return entityManager.createQuery("DELETE FROM BoardTopicCategoryIndex btc WHERE btc.boardId = ?1 AND btc.categoryId IN ?2").setParameter(1, boardId).setParameter(2, categoryIdSet).executeUpdate();
    }
    
    @Override
    public Stream<BoardTopicCategoryIndex> findAllByBoard(long boardId, int boardGroupId) {
        return entityManager.createQuery("SELECT btc FROM BoardTopicCategoryIndex btc WHERE btc.boardId = ?1 OR btc.volumesId = ?2", BoardTopicCategoryIndex.class).setParameter(1, boardId).setParameter(2, boardGroupId).getResultStream();
    }
    /**
     * [NativeSQL]
     * @param boardId
     * @param boardGroupId
     * @return 
     */
    @Override
    public Stream<TopicCategory> findAll(long boardId, int boardGroupId) {
        return entityManager.createNativeQuery("SELECT tc.* FROM apo_topic_category AS tc RIGHT OUTER JOIN apo_board_topic_category_index AS btc ON btc.CATEGORYID = tc.ID WHERE btc.CATEGORYID > ?1 AND ((btc.BOARDID = ?2) OR (btc.BOARDID = ?3 AND btc.VOLUMESID = ?4))", TopicCategory.class)
                .setParameter(1, 0)
                .setParameter(2, boardId)
                .setParameter(3, 0)
                .setParameter(4, boardGroupId)
                .getResultStream();
    }
    
    @Override
    public Stream<BoardTopicCategoryIndex> findAllByCategory(int categoryId) {
        return entityManager.createQuery("SELECT btc FROM BoardTopicCategoryIndex btc WHERE btc.categoryId = ?1", BoardTopicCategoryIndex.class).setParameter(1, categoryId).getResultStream();
    }
    
    @Override
    public Stream<BoardTopicCategoryIndex> findAllByCategory(List<Integer> categoryIdList) {
        if (categoryIdList == null || categoryIdList.isEmpty()) {
            return Stream.empty();
        }
        return entityManager.createQuery("SELECT btc FROM BoardTopicCategoryIndex btc WHERE btc.categoryId IN ?1", BoardTopicCategoryIndex.class).setParameter(1, categoryIdList).getResultStream();
    }
}